﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using CustomAuthorizationDemo.Authentication;
using CustomAuthorizationDemo.Authorization;
using CustomAuthorizationDemo.Security.Session;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Swashbuckle.AspNetCore.Swagger;

namespace CustomAuthorizationDemo
{
    public class Startup
    {

        private static readonly string swaggerDocName = "v1";
        private readonly string corsPolicyName = "CorsPolicy";
        private readonly IConfiguration Configuration;
        private readonly IHostingEnvironment HostingEnvironment;

        public Startup(IConfiguration configuration, IHostingEnvironment env)
        {
            Configuration = configuration;
            HostingEnvironment = env;
            //using (var serviceScope = serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope())
            //{
            //    var env = serviceScope.ServiceProvider.GetRequiredService<IHostingEnvironment>();
            //    var webRoot = env.WebRootPath;
            //}//end using scope
        }


        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
            services.AddHttpContextAccessor(); //ASP.NET Core 2.2之后的版本，必须添加此代码才能注入IHttpContextAccessor实例
            //添加依赖注入
            services.AddSingleton<IClaimsSession, ClaimsSession>();
            services.AddTransient<IAuthenticationService, SampleAuthenticationService>();
            services.AddSingleton<IPermissionChecker, SamplePermissionChecker>();
            //替换控制器构建者类，实现控制器和Filter类属性注入功能
            services.Replace(ServiceDescriptor.Transient<IControllerActivator, DI.PropertiesAutowiredControllerActivator>());
            services.Replace(ServiceDescriptor.Transient<IFilterProvider, DI.PropertiesAutowiredFilterProvider>());
            //添加身份验证
            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = BearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = BearerDefaults.AuthenticationScheme;
            }).AddBearer();

            //跨域
            services.AddCors(options =>
            {
                // CorsPolicy 是自訂的 Policy 名稱
                options.AddPolicy(corsPolicyName, policy =>
                {
                    policy.AllowAnyOrigin()
                          .AllowAnyHeader()
                          .AllowAnyMethod()
                          .AllowCredentials();
                });
            });
            services.AddSwaggerGen(c =>
            {
                c.IgnoreObsoleteActions();
                c.SwaggerDoc(
                    // name: 攸關 SwaggerDocument 的 URL 位置。
                    name: swaggerDocName,
                    // info: 是用於 SwaggerDocument 版本資訊的顯示(內容非必填)。
                    info: new Info
                    {
                        Title = "Custom Authorization Demo",
                        Version = "1.0.0",
                        Description = "自定义权限验证示例",
                        //TermsOfService = "None",
                        //Contact = new Contact { Name = "Jayson Xu", Url = "wiseant@163.com" }
                    }
                );
                var security = new Dictionary<string, IEnumerable<string>> { { "Bearer", new string[] { } } };
                c.AddSecurityRequirement(security);//添加一个必须的全局安全信息，和AddSecurityDefinition方法指定的方案名称要一致，这里是Bearer。
                c.AddSecurityDefinition("Bearer", new ApiKeyScheme
                {
                    Description = "权限认证(数据将在请求头中进行传输) 参数结构: \"Authorization: Bearer {token}\"",
                    Name = "Authorization",//jwt默认的参数名称
                    In = "header",//jwt默认存放Authorization信息的位置(请求头中)
                    Type = "apiKey"
                });//Authorization的设置
                //应用XML注释文档
                var filePath = Path.Combine(HostingEnvironment.ContentRootPath, "Api.xml");
                if (File.Exists(filePath))
                    c.IncludeXmlComments(filePath);
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            //应用身份验证
            app.UseAuthentication();

            //跨域
            app.UseCors(corsPolicyName);

            app.UseMvcWithDefaultRoute();
            app.UseStaticFiles();

            //Swagger
            app.UseSwagger();
            app.UseSwaggerUI(c =>
            {
                c.SwaggerEndpoint(
                    // url: 需配合 SwaggerDoc 的 name。 "/swagger/{SwaggerDoc name}/swagger.json"
                    url: $"../swagger/{swaggerDocName}/swagger.json", //这里一定要使用相对路径，不然网站发布到子目录时将报告："Not Found /swagger/v1/swagger.json"
                                                                      // description: 用於 Swagger UI 右上角選擇不同版本的 SwaggerDocument 顯示名稱使用。
                    name: "RESTful API v1.0.0"
                );
                //c.InjectOnCompleteJavaScript();
            });
        }
    }
}
